package com.bestv.search.engine.compass.extend;

import com.bestv.search.common.model.Info;
import org.compass.core.CompassException;
import org.compass.core.Resource;
import org.compass.core.cascade.CascadingManager;
import org.compass.core.config.RuntimeCompassSettings;
import org.compass.core.events.FilterOperation;
import org.compass.core.impl.DefaultCompassSession;
import org.compass.core.mapping.Cascade;
import org.compass.core.marshall.MarshallingException;
import org.compass.core.spi.DirtyOperationContext;
import org.compass.core.spi.InternalResource;
import org.compass.core.spi.ResourceKey;

public class DefaultCompassSessionExtend extends DefaultCompassSession {

    private final CascadingManager cascadingManager;

    public DefaultCompassSessionExtend(DefaultCompassSession session) {
        super(new RuntimeCompassSettings(session.getSettings()), session
                .getCompass(), session.getSearchEngine(), session
                .getFirstLevelCache());
        this.cascadingManager = new CascadingManager(this);
    }

    @Override
    public void create(Object object, DirtyOperationContext context)
            throws CompassException {
        if (!(object instanceof Info)) {
            super.create(object, context);
            return;
        }
        Info info = (Info) object;
        if (context.alreadyPerformedOperation(object)) {
            return;
        }
        if (getCompass().getEventManager().onPreCreate(null, object) == FilterOperation.YES) {
            return;
        }
        boolean performedCascading;
        Resource resource = super.getMarshallingStrategy().marshall(object);
        if (resource != null) {
            resource.setBoost(info.getBoost());
            if (getCompass().getEventManager().onPreCreate(resource) == FilterOperation.YES) {
                return;
            }
            getSearchEngine().create(resource);
            ResourceKey key = ((InternalResource) resource).getResourceKey();

            getFirstLevelCache().set(key, object);
            getFirstLevelCache().setResource(key, resource);
            context.addOperatedObjects(object);
            // if we found a resource, we perform the cascading based on its
            // alias
            performedCascading = cascadingManager.cascade(key.getAlias(),
                    object, Cascade.CREATE, context);
        } else {
            context.addOperatedObjects(object);
            performedCascading = cascadingManager.cascade(object,
                    Cascade.CREATE, context);
        }
        if (resource == null && !performedCascading) {
            throw new MarshallingException(
                    "Object ["
                            + object.getClass().getName()
                            + "] has no root mappings and no cascading defined, no operation was perfomed");
        }
        if (resource != null) {
            getCompass().getEventManager().onPostCreate(resource);
            getCompass().getEventManager().onPostCreate(resource.getAlias(),
                    object);
        } else {
            getCompass().getEventManager().onPostCreate(null, object);
        }
    }

    @Override
    public void create(String alias, Object object,
                       DirtyOperationContext context) throws CompassException {
        if (!(object instanceof Info)) {
            super.create(alias, object, context);
            return;
        }
        Info info = (Info) object;
        if (context.alreadyPerformedOperation(object)) {
            return;
        }
        if (getCompass().getEventManager().onPreCreate(alias, object) == FilterOperation.YES) {
            return;
        }
        Resource resource = getMarshallingStrategy().marshall(alias, object);
        if (resource != null) {
            resource.setBoost(info.getBoost());
            if (getCompass().getEventManager().onPreCreate(resource) == FilterOperation.YES) {
                return;
            }
            getSearchEngine().create(resource);
            ResourceKey key = ((InternalResource) resource).getResourceKey();
            getFirstLevelCache().set(key, object);
            getFirstLevelCache().setResource(key, resource);
        }
        context.addOperatedObjects(object);
        boolean performedCascading = cascadingManager.cascade(alias, object,
                Cascade.CREATE, context);
        if (resource == null && !performedCascading) {
            throw new MarshallingException(
                    "Alias ["
                            + alias
                            + "] has no root mappings and no cascading defined, no operation was perfomed");
        }
        if (resource != null) {
            getCompass().getEventManager().onPostCreate(resource);
        }
        getCompass().getEventManager().onPostCreate(alias, object);
    }

    public CascadingManager getCascadingManager() {
        return cascadingManager;
    }
}
